package cn.iocoder.yudao.framework.business.sse.service;

import cn.iocoder.yudao.framework.business.sse.pojo.SseDataType;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  Server-Sent Events (SSE)，参阅 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events/Using_server-sent_events">Using server-sent events</a>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/03/15
 */
@Service
public class SseServiceImpl implements SseService {
    private final Set<SseEmitter> emitters = ConcurrentHashMap.newKeySet();

    @Override
    public SseEmitter subscribe() {
        SseEmitter emitter = new SseEmitter(60_000L);
        emitter.onCompletion(() -> emitters.remove(emitter));
        emitters.add(emitter);
        return emitter;
    }

    @Override
    public void broadcast(SseDataType data) {
        emitters.forEach(emitter -> {
            try {
                emitter.send(SseEmitter.event()
                        .data(JsonUtils.toJsonString(data))
                        .id(UUID.randomUUID().toString()));
            } catch (IOException e) {
                emitter.completeWithError(e);
            }
        });
    }

}
